package com.ruoyi.alert.service.impl;

import cn.hutool.core.util.ObjectUtil;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ruoyi.alert.domain.IotAlert;
import com.ruoyi.alert.domain.IotAlertLog;
import com.ruoyi.alert.domain.IotAlertOperator;
import com.ruoyi.alert.mapper.IotAlertLogMapper;
import com.ruoyi.alert.service.IIotAlertLogService;

import com.ruoyi.alert.service.IIotAlertOperatorService;
import com.ruoyi.alert.service.IIotAlertService;
import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.iot.domain.IotSensor;
import com.ruoyi.iot.domain.IotStation;
import com.ruoyi.iot.domain.IotFuncDict;
import com.ruoyi.iot.enums.SensorWarningStatusEnum;
import com.ruoyi.iot.service.IIotFuncDictService;
import com.ruoyi.iot.service.IotSensorService;
import com.ruoyi.iot.service.IotStationService;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.*;
import java.util.concurrent.atomic.AtomicReference;
import java.util.stream.Collectors;

/**
 * 设备告警日志Service业务层处理
 *
 * @author ruoyi
 * @date 2025-07-03
 */
@RequiredArgsConstructor
@Service
public class IotAlertLogServiceImpl extends ServiceImpl<IotAlertLogMapper, IotAlertLog> implements IIotAlertLogService {

    @Resource
    private IotAlertLogMapper baseMapper;

    @Resource
    private IIotAlertService alertService;

    @Resource
    private IIotAlertOperatorService alertOperatorService;

    @Resource
    private IIotFuncDictService funcDictService;
    @Resource
    private IotStationService iotStationService;
    @Resource
    private IotSensorService iotSensorService;



    @Override
    public void hanlerAlert(String tableName, Map<String, String> tags, Map<String, Object> stringObjectMap) {
        //根据tableName->alert.alertType找告警配置 根据tags中的deviceId或者remoteId->bind_id找告警配置

        //如果存在多个告警配置 优先选择应用在单个设备的

        // 边界条件检查
        if (tableName == null || tableName.isEmpty()) {
            throw new IllegalArgumentException("Measurement cannot be null or empty");
        }
        if (tags == null || tags.isEmpty() || stringObjectMap == null || stringObjectMap.isEmpty()) {
            throw new IllegalArgumentException("Tags and stringObjectMap cannot be null or empty");
        }
        // 获取 deviceId
        String deviceId = tags.get("remote_id");
        if (deviceId == null || deviceId.isEmpty()) {
            throw new IllegalArgumentException("remoteId cannot be null or empty");
        }
        String sensorId = tags.get("device_id");
        if( sensorId == null || sensorId.isEmpty()) {
            throw new IllegalArgumentException("deviceId cannot be null or empty");
        }
        LambdaQueryWrapper<IotAlert> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(IotAlert::getAlertType, tableName);
        queryWrapper.eq(IotAlert::getStatus, 1); //启用
        List<IotAlert> alertConfigs = alertService.list(queryWrapper);

        if(ObjectUtil.isEmpty(alertConfigs)) {
            return ;
        }

        //获取作用于单个设备的告警配置
        List<IotAlert> singleDeviceAlertConfigs = alertConfigs.stream().filter(alertConfig -> ("2".equals(alertConfig.getBindType() ) && alertConfig.getBindId().equals(sensorId))).collect(Collectors.toList());

        List<IotAlert> deviceAlertConfigs = new ArrayList<>();
        if( ObjectUtil.isNotEmpty(singleDeviceAlertConfigs) ) {
            deviceAlertConfigs =singleDeviceAlertConfigs;
        } else {
            //获取作用于多个设备的告警配置
            List<IotAlert> multiDeviceAlertConfigs = alertConfigs.stream().filter(alertConfig -> "1".equals(alertConfig.getBindType())).collect(Collectors.toList());
            deviceAlertConfigs = multiDeviceAlertConfigs;
        }
        //遍历 根据每条配置判断是否生成相应的日志
        Map<String, String> funcDictMap = funcDictService.list().stream().filter(iotFuncDict -> iotFuncDict.getTableName().equals(tableName)).collect(Collectors.toMap(IotFuncDict::getFieldName, IotFuncDict::getFieldType, (existing, replacement) -> replacement));
        deviceAlertConfigs.forEach(alertConfig -> {
            List<IotAlertOperator> iotAlertOperatorList = alertOperatorService.list(
                new LambdaQueryWrapper<IotAlertOperator>().eq(IotAlertOperator::getAlertId, alertConfig.getAlertId()));
            AtomicReference<Boolean> flag = new AtomicReference<>(ObjectUtil.isNotEmpty(iotAlertOperatorList));
            String connectType = alertConfig.getConnectType();
            AtomicReference<Boolean> isFirst = new AtomicReference<>(Boolean.TRUE);
            // 替换原来的 List<Map<String, Object>> properties = new ArrayList<>();
            Map<String, Map<String, Object>> propertyMap = new LinkedHashMap<>();

            iotAlertOperatorList.forEach(op -> {
                String operator = op.getOperator();
                String value = op.getValue();
                String name = op.getName();
                String unit = op.getUnit();
                String valueType = funcDictMap.get(name);

                Object fieldValue = stringObjectMap.get(name);

                if (fieldValue == null || value == null) {
                    flag.set(false);
                    return;
                }

                // 构建 compare 对象
                Map<String, Object> compareItem = new HashMap<>();
                compareItem.put("value", value);
                compareItem.put("operator", operator);

                if (!propertyMap.containsKey(name)) {
                    // 第一次遇到该 name，创建主对象
                    Map<String, Object> property = new HashMap<>();
                    property.put("name", name);
                    property.put("fieldValue", fieldValue);
                    property.put("valueType", valueType);
                    property.put("unit", unit);
                    List<Map<String, Object>> compareList = new ArrayList<>();
                    compareList.add(compareItem);
                    property.put("compare", compareList);
                    propertyMap.put(name, property);
                } else {
                    // 已存在，只追加 compare
                    Map<String, Object> existing = propertyMap.get(name);
                    @SuppressWarnings("unchecked")
                    List<Map<String, Object>> compareList = (List<Map<String, Object>>) existing.get("compare");
                    compareList.add(compareItem);
                }

                // 条件判断逻辑不变
                boolean conditionMet = false;
                try {
                    switch (valueType) {
                        case "int":
                            int intValue = Integer.parseInt(fieldValue.toString());
                            int opIntValue = Integer.parseInt(value);
                            conditionMet = compare(operator, intValue, opIntValue);
                            break;
                        case "double":
                            double doubleValue = Double.parseDouble(fieldValue.toString());
                            double opDoubleValue = Double.parseDouble(value);
                            conditionMet = compare(operator, doubleValue, opDoubleValue);
                            break;
                        case "float":
                            float floatValue = Float.parseFloat(fieldValue.toString());
                            float opFloatValue = Float.parseFloat(value);
                            conditionMet = compare(operator, floatValue, opFloatValue);
                            break;
                        case "boolean":
                            boolean boolValue = Boolean.parseBoolean(fieldValue.toString());
                            boolean opBoolValue = Boolean.parseBoolean(value);
                            conditionMet = compare(operator, boolValue, opBoolValue);
                            break;
                        case "string":
                        default:
                            conditionMet = compare(operator, fieldValue.toString(), value);
                            break;
                    }
                } catch (NumberFormatException e) {
                    throw new IllegalArgumentException("Failed to parse value for type: " + valueType, e);
                }

                if (isFirst.get()) {
                    flag.set(conditionMet);
                    isFirst.set(false);
                } else {
                    if (Objects.equals(connectType, "and")) {
                        flag.set(flag.get() && conditionMet);
                    } else if (Objects.equals(connectType, "or")) {
                        flag.set(flag.get() || conditionMet);
                    }
                }
            });

            if (flag.get()) {
                // 转换为最终的 list
                List<Map<String, Object>> properties = new ArrayList<>(propertyMap.values());

                IotAlertLog alertLog = new IotAlertLog();
                alertLog.setAlertId(alertConfig.getAlertId());
                alertLog.setAlertLevel(alertConfig.getAlertLevel());
                alertLog.setAlertName(alertConfig.getAlertName());
                alertLog.setDetail(JSON.toJSONString(properties));
                alertLog.setStatus(2L);
                Date now = new Date();
                alertLog.setCreateTime(now);
                alertLog.setUpdateTime(now);

                // 获取设备信息
                LambdaQueryWrapper<IotSensor> sensorLambdaQueryWrapper = Wrappers.lambdaQuery();
                sensorLambdaQueryWrapper.eq(IotSensor::getSensorId, sensorId);
                IotSensor sensorInfo = iotSensorService.getOne(sensorLambdaQueryWrapper);
                alertLog.setDeviceId(deviceId);
                alertLog.setSensorId(sensorId);

                String alertContent = "";
                if(ObjectUtil.isNotEmpty(sensorInfo)) {
                    LambdaQueryWrapper<IotStation> stationLambdaQueryWrapper = Wrappers.lambdaQuery();
                    stationLambdaQueryWrapper.eq(IotStation::getStationId, sensorInfo.getStationId());
                    IotStation stationInfo = iotStationService.getOne(stationLambdaQueryWrapper);


                    alertLog.setStationId(stationInfo.getStationId());
                    alertLog.setLongitude(stationInfo.getLongitude());
                    alertLog.setLatitude(stationInfo.getLatitude());
                    alertContent = alertConfig.getAlertName() + "：" + stationInfo.getStationName() +
                            "于" + DateUtils.parseDateToStr("yyyy-MM-dd HH:mm:ss", now) + "发生预警，" +
                            properties.stream().map(property -> property.get("name") + "为" + property.get("fieldValue")).collect(Collectors.joining(", "));
                    alertLog.setAlertContent(alertContent);
                }

                this.save(alertLog);

                iotSensorService.updateSensorWarnStatus(sensorId, SensorWarningStatusEnum.WARNING.getCode(),  JSON.toJSONString(properties), alertContent);
                //设置对应设备为告警状态

            } else {
                // 告警未触发
                iotSensorService.updateSensorWarnStatus(sensorId, SensorWarningStatusEnum.NORMAL.getCode(), null, null);
            }

        });
    }

    private <T extends Comparable<T>> boolean compare(String operator, T v1, T v2) {
        switch (operator) {
            case ">": return v1.compareTo(v2) > 0;
            case "<": return v1.compareTo(v2) < 0;
            case ">=": return v1.compareTo(v2) >= 0;
            case "<=": return v1.compareTo(v2) <= 0;
            case "=": return v1.equals(v2);
            case "!=": return !v1.equals(v2);
            default: throw new IllegalArgumentException("Unsupported operator: " + operator);
        }
    }


}
